package com.ruoyi.common.utils.date;

import lombok.Data;
import lombok.ToString;
import org.apache.commons.lang3.StringUtils;
import org.apache.commons.lang3.math.NumberUtils;

import java.io.Serializable;
import java.util.*;
import java.util.regex.Matcher;
import java.util.regex.Pattern;

@Data
@ToString(callSuper = false)
public class Time implements Serializable, Comparable<Time> {
	private static final long serialVersionUID = -4480065933572389325L;
	private int hour = 0;
	private int minute = 0;
	private int second = 0;

	public Time() {
	}

	public Time(int hour, int minute, int second) {
		Calendar calendar = Calendar.getInstance(Locale.CHINA);
		calendar.set(Calendar.HOUR_OF_DAY, hour);
		calendar.set(Calendar.MINUTE, minute);
		calendar.set(Calendar.SECOND, second);
		this.hour = calendar.get(Calendar.HOUR_OF_DAY);
		this.minute = calendar.get(Calendar.MINUTE);
		this.second = calendar.get(Calendar.SECOND);
	}

	public Time(Date date) {
		Calendar calendar = Calendar.getInstance(Locale.CHINA);
		calendar.setTime(date);
		this.hour = calendar.get(Calendar.HOUR_OF_DAY);
		this.minute = calendar.get(Calendar.MINUTE);
		this.second = calendar.get(Calendar.SECOND);
	}

	public Time(Calendar calendar) {
		this.hour = calendar.get(Calendar.HOUR_OF_DAY);
		this.minute = calendar.get(Calendar.MINUTE);
		this.second = calendar.get(Calendar.SECOND);
	}

	public Time add(int field, int amount) {
		Set<Integer> set = new HashSet<Integer>();
		set.add(Calendar.HOUR_OF_DAY);
		set.add(Calendar.MINUTE);
		set.add(Calendar.SECOND);
		if (!set.contains(field)) {
			throw new IllegalArgumentException("Invalid field");
		}
		Calendar calendar = Calendar.getInstance(Locale.CHINA);
		calendar.set(Calendar.HOUR_OF_DAY, this.hour);
		calendar.set(Calendar.MINUTE, this.minute);
		calendar.set(Calendar.SECOND, this.second);

		calendar.add(field, amount);
		Time time = new Time(calendar.get(Calendar.HOUR_OF_DAY), calendar.get(Calendar.MINUTE),
				calendar.get(Calendar.SECOND));
		return time;
	}

	/**
	 * 获取与当前日期同一天的时间点
	 * 
	 * @return
	 */
	public Date getTimeDate() {
		Calendar calendar = Calendar.getInstance(Locale.CHINA);
		calendar.set(Calendar.HOUR_OF_DAY, this.hour);
		calendar.set(Calendar.MINUTE, this.minute);
		calendar.set(Calendar.SECOND, this.second);
		return calendar.getTime();
	}

	/**
	 * 获取与指定日期同一天的时间点
	 * 
	 * @param date
	 * @return
	 */
	public Date getTimeDate(Date date) {
		Calendar calendar = Calendar.getInstance(Locale.CHINA);
		calendar.setTime(date);
		calendar.set(Calendar.HOUR_OF_DAY, this.hour);
		calendar.set(Calendar.MINUTE, this.minute);
		calendar.set(Calendar.SECOND, this.second);
		return calendar.getTime();
	}

	public static Time parseTime(String time) {
		String regex = "((\\d{1,2}):(\\d{1,2}):(\\d{1,2}))";
		time = StringUtils.trimToEmpty(time);
		Matcher matcher = Pattern.compile(regex).matcher(time);
		if (matcher.matches()) {
			Time resTime = new Time();
			String strHour = StringUtils.trimToEmpty(time.replaceAll(regex, "$2"));
			if (NumberUtils.isDigits(strHour)) {
				int hour = Integer.valueOf(strHour);
				if (0 <= hour && hour <= 23) {
					resTime.setHour(hour);
				}
			}
			String strMinute = StringUtils.trimToEmpty(time.replaceAll(regex, "$3"));
			if (NumberUtils.isDigits(strMinute)) {
				int minute = Integer.valueOf(strMinute);
				if (0 <= minute && minute <= 59) {
					resTime.setMinute(minute);
				}
			}
			String strSecond = StringUtils.trimToEmpty(time.replaceAll(regex, "$4"));
			if (NumberUtils.isDigits(strSecond)) {
				int second = Integer.valueOf(strSecond);
				if (0 <= second && second <= 59) {
					resTime.setSecond(second);
				}
			}
			return resTime;
		}
		return null;
	}

	@Override
	public int compareTo(Time other) {
		Date date = this.getTimeDate();
		Date oDate = other.getTimeDate();
		return date.compareTo(oDate);
	}

	public String toString() {
		String res = String.format("%02d:%02d:%02d", this.hour, this.minute, this.second);
		return res;
	}
}
